﻿using System.AutoUpdate.Core.Sources;
using System.AutoUpdate.Library;
using System.AutoUpdate.Security;
using System.AutoUpdate.Tools;

namespace System.AutoUpdate.Sources
{
    /// <summary>
    /// Basic text web update source
    /// </summary>
    public class TextWebSource : WebSource
    {
        private readonly string _uri;
        private readonly string _versionCommand;
        private readonly string _downloadFolder;

        /// <summary>
        /// Creates new text web source on URI
        /// </summary>
        /// <param name="uri">URL of the source repository</param>
        /// <param name="versionCommand">Appended to URL to get version lists and hashes</param>
        /// <param name="downloadFolder">Appended to URL to download files</param>
        public TextWebSource (string uri, string versionCommand, string downloadFolder)
        {
            _uri = uri;
            _versionCommand = versionCommand;
            _downloadFolder = downloadFolder;

            //
            // Make sure we have slash on end
            //

            if (!_uri.EndsWith ("/") )
            {
                _uri = _uri + "/";
            }

            if (!_downloadFolder.EndsWith("/"))
            {
                _downloadFolder = _downloadFolder + "/";
            }

            LoadVersions ();
        }

        /// <summary>
        /// Loads version list from simple web source, using ; and | characters, respectively
        /// </summary>
        protected override sealed void LoadVersions ()
        {
            AvailableVersions.Clear();

            if (VersionParser == null)
            {
                VersionParser = new UpdateVersionParser ();
            }

            string versionString = DownloadString(_uri + _versionCommand).Replace ("\n", "").Replace ("\r", "").Trim ();

            AvailableVersions.Clear ();

            if (String.IsNullOrEmpty (versionString))
            {
                return;
            }

            string[] versions = versionString.Split (';');

            //
            // Parse version list
            //

            foreach (string version in versions)
            {
                string[] versionData = version.Split ('|');

                //
                // Need 5 basic parameters
                //

                if (versionData.Length != 5)
                {
                    continue;
                }

                DateTime releaseTime = DateTime.Parse (versionData[1]);

                //
                // Create versionInfo
                //

                UpdateVersionInfo versionInfo = new UpdateVersionInfo (VersionParser.Parse (versionData[0]), GetFileSize (_uri + _downloadFolder + versionData[2]), releaseTime)
                                                {
                                                    File =
                                                    {
                                                        Hash = versionData[3].ToUpper(),
                                                        HashType = (HashAlgorithmType) Enum.Parse (typeof (HashAlgorithmType), versionData[4]),
                                                        RemotePath = _uri + _downloadFolder
                                                    }
                                                };

                AvailableVersions.Add (versionInfo, versionData[2]);
            }
        }

        /// <summary>
        /// Transfers version file async
        /// </summary>
        /// <param name="info"></param>
        public override void Transfer (UpdateVersionInfo info)
        {
            if (!HasVersion (info))
            {
                return;
            }

            DownloadFile (info.File.RemotePath + AvailableVersions[info], info.File.AbsoluteLocalPath);
        }

        public override bool CheckSignature (UpdateVersionInfo info, bool online = false)
        {
            //
            // Reload versions from online source, so we get new set of versions
            //

            if (online)
            {
                LoadVersions ();
            }

            return HashAlgorithmProvider.HashFileMatch (info);
        }
    }
}
